package jbase.project.system.draw;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;

import javax.imageio.ImageIO;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;

public class MathFun {

	private ScriptEngine se = null;

	public byte[] make(String jsExpress) {
		BufferedImage bi = new BufferedImage(500, 500, BufferedImage.TYPE_INT_RGB);
		Graphics g = bi.getGraphics();
		paint(g, jsExpress, 500, 500, 20, 20);
		ByteArrayOutputStream bos = new ByteArrayOutputStream();
		try {
			ImageIO.write(bi, "png", (OutputStream) bos);
			return bos.toByteArray();
		} catch (IOException e) {
			return new byte[] {};
		}
	}

	public MathFun() throws ScriptException {
		se = new ScriptEngineManager().getEngineFactories().get(0).getScriptEngine();
		se.eval(" function sin(x){ return java.lang.Math.sin(x); }");
		se.eval(" function arcsin(x){ return java.lang.Math.asin(x); }");
		se.eval(" function cos(x){ return java.lang.Math.cos(x); }");
		se.eval(" function arccos(x){ return java.lang.Math.acos(x); }");
		se.eval(" function tan(x){ return java.lang.Math.tan(x); }");
		se.eval(" function cot(x){ return 1/java.lang.Math.tan(x); }");
		se.eval(" function exp(x){ return java.lang.Math.exp(x); }");
		se.put("e", Math.E);
		se.put("PI", Math.PI);
		se.eval(" function pow(a,b){ return java.lang.Math.pow(a,b); }");
		se.eval(" function ln(x){ return java.lang.Math.log(x); }");
		se.eval(" function log(a,b){ return java.lang.Math.log(a)/java.lang.Math.log(b); }");
		se.eval(" function abs(a){ return java.lang.Math.abs(a); }");
	}

	public void paint(Graphics g, String fun, int hPix, int wPix, double xw, double yh) {
		g.setColor(new Color(255, 255, 233));
		int height = hPix;
		int width = wPix;
		g.drawLine(width / 2, 0, width / 2, height);
		g.drawLine(0, height / 2, width, height / 2);
		int iodx = -1;
		int iody = -1;
		try {
			double step = (xw / 2) / (width / 2);
			for (double x = -xw / 2; x <= xw / 2; x += step) {
				se.put("x", x);
				double y = 0D;
				Object rs = se.eval(fun);
				if (rs.getClass() == Integer.class || rs.getClass() == int.class) {
					y = Double.valueOf((Integer) rs);
				} else {
					y = (double) rs;
				}
				int dx = (int) (width / 2 + x * (width / xw));
				int dy = (int) (-y * (height / yh) + height / 2);
				try {
					if (iodx > 0 && iody > 0) {
						g.drawLine(iodx, iody, dx, dy);
					} else {
						g.drawOval(dx, dy, 1, 1);
					}
					iodx = dx;
					iody = dy;
				} catch (Exception e1) {
					e1.printStackTrace();
				}
			}
		} catch (ScriptException e1) {
			e1.printStackTrace();
		}
	}

}
